import js from '@eslint/js'
import stylistic from '@stylistic/eslint-plugin'
import ts from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'
import parensIndent from '@urchick/eslint-plugin-parens-indent'
import globals from 'globals'

export default [
    stylistic.configs.customize({
        indent: 4,
        quotes: 'single',
        semi: false,
        jsx: false,
        braceStyle: '1tbs',
        quoteProps: 'as-needed',
        commaDangle: 'always-multiline',
    }),
    {
        files: [
            'src/**/*.ts',
            'test/**/*.ts',
        ],
        plugins: {
            '@stylistic': stylistic,
            '@typescript-eslint': ts,
            '@urchick/parens-indent': parensIndent,
        },
        languageOptions: {
            parser: tsParser,
            parserOptions: {
                sourceType: 'module',
                ecmaFeatures: {
                    jsx: true,
                },
                project: './tsconfig.json',
            },
            globals: {
                ...globals.browser,
                ...globals.builtin,
                ...globals.es2021,
            },
        },
        linterOptions: {
            reportUnusedDisableDirectives: true,
        },
        rules: {
            ...js.configs.recommended.rules,
            ...ts.configs['eslint-recommended'].overrides[0].rules,
            ...ts.configs['strict-type-checked'].rules,
            ...ts.configs['stylistic-type-checked'].rules,
            'no-cond-assign': [
                2,
                'except-parens',
            ],
            'no-constant-condition': 2,
            'no-debugger': 2,
            'no-duplicate-case': 2,
            'no-empty-character-class': 2,
            'no-empty': [
                2,
                {
                    allowEmptyCatch: true,
                },
            ],
            'no-ex-assign': 2,
            'no-extra-boolean-cast': 2,
            'no-invalid-regexp': 2,
            'no-irregular-whitespace': 2,
            'no-sparse-arrays': 2,
            'no-unexpected-multiline': 2,
            'curly': [
                2,
                'multi',
            ],
            'dot-notation': [
                2,
                {
                    allowKeywords: true,
                },
            ],
            'no-caller': 2,
            'no-else-return': [
                2,
                {
                    allowElseIf: false,
                },
            ],
            'no-eq-null': 2,
            'no-eval': 2,
            'no-extend-native': 2,
            'no-extra-bind': 2,
            'no-iterator': 2,
            'no-labels': [
                2,
                {
                    allowLoop: true,
                },
            ],
            'no-lone-blocks': 2,
            'no-multi-str': 2,
            'no-native-reassign': 2,
            'no-new-func': 2,
            'no-new-wrappers': 2,
            'no-new': 2,
            'no-octal-escape': 2,
            'no-octal': 2,
            'no-proto': 2,
            'no-script-url': 2,
            'no-self-compare': 2,
            '@typescript-eslint/no-unused-expressions': [
                2,
                {
                    allowShortCircuit: true,
                    enforceForJSX: true,
                },
            ],
            '@typescript-eslint/no-unused-vars': 0,
            'no-useless-call': 2,
            'no-void': 2,
            'no-with': 2,
            radix: 2,
            '@stylistic/wrap-iife': [
                2,
                'outside',
            ],
            'no-label-var': 2,
            'no-undef-init': 2,
            '@typescript-eslint/no-namespace': 0,
            '@stylistic/linebreak-style': [
                0,
            ],
            'new-cap': [
                2,
                {
                    newIsCap: true,
                    capIsNew: false,
                },
            ],
            'no-lonely-if': 2,
            'no-object-constructor': 2,
            'no-spaced-func': 2,
            'no-unneeded-ternary': 2,
            '@stylistic/object-curly-spacing': [
                2,
                'never',
                {
                    arraysInObjects: false,
                    objectsInObjects: false,
                },
            ],
            'operator-assignment': [
                2,
                'always',
            ],
            'logical-assignment-operators': [
                2,
                'always',
                {
                    enforceForIfStatements: true,
                },
            ],
            '@stylistic/operator-linebreak': [
                2,
                'after',
                {
                    overrides: {
                        '?': 'before',
                        ':': 'before',
                    },
                },
            ],
            '@stylistic/no-mixed-operators': 0,
            '@stylistic/padded-blocks': [
                2,
                'never',
            ],
            'id-match': 2,
            '@stylistic/space-before-function-paren': [
                2,
                'never',
            ],
            '@stylistic/arrow-parens': [
                2,
                'as-needed',
            ],
            '@stylistic/yield-star-spacing': [
                2,
                {
                    before: false,
                    after: true,
                },
            ],
            'object-shorthand': [
                2,
                'always',
            ],
            'require-yield': 2,
            'no-negated-condition': 2,
            'no-unsafe-finally': 2,
            'no-extra-label': 2,
            'no-implicit-globals': 2,
            '@stylistic/max-len': [
                2,
                150,
            ],
            'prefer-template': 2,
            '@stylistic/indent': [
                2,
                4,
                {
                    SwitchCase: 0,
                },
            ],
            'prefer-destructuring': [
                2,
                {
                    object: true,
                    array: true,
                },
            ],
            '@stylistic/newline-per-chained-call': 2,
            'require-atomic-updates': 2,
            'no-async-promise-executor': 2,
            'prefer-object-spread': 2,
            'no-return-await': 2,
            'no-useless-catch': 2,
            'no-useless-rename': 2,
            'grouped-accessor-pairs': 2,
            'no-dupe-else-if': 2,
            'prefer-exponentiation-operator': 2,
            'prefer-regex-literals': [
                2,
                {
                    disallowRedundantWrapping: true,
                },
            ],
            '@typescript-eslint/default-param-last': 2,
            'no-nonoctal-decimal-escape': 2,
            'no-unreachable-loop': 2,
            'no-useless-backreference': 2,
            'no-restricted-syntax': [
                2,
                {
                    selector: 'FunctionDeclaration > AssignmentPattern > TSAsExpression, FunctionExpression > AssignmentPattern > TSAsExpression, ArrowFunctionExpression > AssignmentPattern > TSAsExpression',
                    message: 'Specify parameter type instead of initializer assertion',
                },
                {
                    selector: 'ArrowFunctionExpression > BlockStatement[body.length=1] > ReturnStatement',
                    message: 'Prefer concise function body',
                },
            ],
            '@stylistic/nonblock-statement-body-position': [
                2,
                'below',
            ],
            '@stylistic/new-parens': [
                2,
                'never',
            ],
            '@stylistic/block-spacing': [
                2,
                'never',
            ],
            '@stylistic/padding-line-between-statements': [
                2,
                {
                    blankLine: 'always',
                    prev: 'block-like',
                    next: '*',
                },
                {
                    blankLine: 'always',
                    prev: [
                        'const',
                        'let',
                    ],
                    next: [
                        'block-like',
                        'if',
                        'for',
                        'while',
                    ],
                },
                {
                    blankLine: 'any',
                    prev: [
                        'const',
                        'let',
                    ],
                    next: [
                        'const',
                        'let',
                    ],
                },
                {
                    blankLine: 'always',
                    prev: [
                        'block-like',
                        'multiline-expression',
                        'multiline-const',
                        'multiline-let',
                        'if',
                        'for',
                        'while',
                    ],
                    next: 'return',
                },
            ],
            '@typescript-eslint/non-nullable-type-assertion-style': 0,
            '@typescript-eslint/consistent-indexed-object-style': 0,
            '@typescript-eslint/consistent-type-assertions': 0,
            '@typescript-eslint/consistent-type-definitions': 0,
            '@typescript-eslint/naming-convention': [
                2,
                {
                    selector: 'variable',
                    modifiers: [
                        'exported',
                        'const',
                    ],
                    format: [
                        'camelCase',
                        'UPPER_CASE',
                        'PascalCase',
                    ],
                    leadingUnderscore: 'allow',
                    trailingUnderscore: 'allow',
                },
                {
                    selector: 'variable',
                    format: [
                        'camelCase',
                        'PascalCase',
                    ],
                    leadingUnderscore: 'allow',
                    trailingUnderscore: 'allow',
                },
                {
                    selector: 'typeLike',
                    format: [
                        'PascalCase',
                    ],
                },
                {
                    selector: [
                        'function',
                        'parameter',
                    ],
                    format: [
                        'camelCase',
                        'PascalCase',
                    ],
                    leadingUnderscore: 'allow',
                    trailingUnderscore: 'allow',
                },
            ],
            '@stylistic/no-extra-parens': [
                2,
                'all',
            ],
            '@stylistic/lines-between-class-members': [
                2,
                'always',
                {
                    exceptAfterOverload: true,
                    exceptAfterSingleLine: true,
                },
            ],
            '@typescript-eslint/only-throw-error': 0,
            '@typescript-eslint/no-confusing-void-expression': 0,
            '@typescript-eslint/no-this-alias': 0,
            '@typescript-eslint/no-throw-literal': 0,
            '@typescript-eslint/no-unnecessary-qualifier': 2,
            '@typescript-eslint/no-useless-empty-export': 2,
            '@typescript-eslint/prefer-nullish-coalescing': 0,
            '@typescript-eslint/prefer-readonly': 2,
            '@typescript-eslint/prefer-regexp-exec': 2,
            '@typescript-eslint/require-array-sort-compare': [
                2,
                {
                    ignoreStringArrays: true,
                },
            ],
            '@typescript-eslint/restrict-template-expressions': 0,
            '@typescript-eslint/switch-exhaustiveness-check': 2,
            '@typescript-eslint/consistent-type-imports': 2,
            '@typescript-eslint/consistent-type-exports': 2,
            '@typescript-eslint/unbound-method': 0,
            '@urchick/parens-indent/parens-proper-indent': 2,
            '@stylistic/member-delimiter-style': [
                2,
                {
                    multiline: {
                        delimiter: 'none',
                    },
                    singleline: {
                        delimiter: 'comma',
                    },
                },
            ],
        },
    },
]
